package com.dzm.xgb.core.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dzm.common.constants.RedisConstants;
import com.dzm.common.exception.Assert;
import com.dzm.common.result.ResponseEnum;
import com.dzm.common.util.JwtUtils;
import com.dzm.common.util.RegexValidateUtils;
import com.dzm.xgb.core.mapper.UserAccountMapper;
import com.dzm.xgb.core.mapper.UserLoginRecordMapper;
import com.dzm.xgb.core.pojo.entity.UserAccount;
import com.dzm.xgb.core.pojo.entity.UserInfo;
import com.dzm.xgb.core.mapper.UserInfoMapper;
import com.dzm.xgb.core.pojo.entity.UserLoginRecord;
import com.dzm.xgb.core.pojo.vo.*;
import com.dzm.xgb.core.service.UserAccountService;
import com.dzm.xgb.core.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dzm.xgb.core.service.UserLoginRecordService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 用户基本信息 服务实现类
 * </p>
 *
 * @author Dzm
 * @since 2024-08-27
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserAccountMapper userAccountMapper;

    @Autowired
    private UserLoginRecordMapper userLoginRecordMapper;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void register(RegisterVo vo) {
        //1.用户信息验证
        //数据校验
        String phoneNumber = vo.getPhoneNumber();
        String code = vo.getCode();
        String password = vo.getPassword();

        Assert.notNull(phoneNumber, ResponseEnum.MOBILE_NULL_ERROR);
        Assert.notNull(code, ResponseEnum.CODE_NULL_ERROR);
        Assert.notNull(password, ResponseEnum.PASSWORD_NULL_ERROR);

        Assert.isTrue(RegexValidateUtils.checkCellphone(phoneNumber), ResponseEnum.MOBILE_ERROR);
        String validCode = (String) redisTemplate.opsForValue().get(RedisConstants.PHONE_CODE + phoneNumber);
        Assert.equals(code, validCode, ResponseEnum.CODE_ERROR);

        //判断用户是否存在
        Integer count = userInfoMapper.selectCount(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getMobile, phoneNumber));
        Assert.isTrue(count.equals(0), ResponseEnum.MOBILE_EXIST_ERROR);

        //2.用户注册
        //用户数据构建
        UserInfo userInfo = new UserInfo();
        userInfo.setMobile(phoneNumber);
        userInfo.setPassword(SecureUtil.md5(password));
        userInfo.setHeadImg("https://daxigua-dzm.oss-cn-shenzhen.aliyuncs.com/2024/08/31/014806fb9a7c46b3a72d0724cd51b544.jpg");
        userInfo.setStatus(UserInfo.STATUS_NORMAL);
        userInfo.setUserType(vo.getUserType());
        userInfo.setName(phoneNumber);
        userInfo.setNickName(phoneNumber);
        userInfoMapper.insert(userInfo);

        //账户数据构建
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userInfo.getId());
        userAccountMapper.insert(userAccount);

    }

    @Override
    public UserInfoVo login(LoginVo vo, String ip) {
        //1.数据校验
        String phoneNumber = vo.getPhoneNumber();
        String password = vo.getPassword();
        Assert.notNull(phoneNumber, ResponseEnum.MOBILE_NULL_ERROR);
        Assert.notNull(password, ResponseEnum.PASSWORD_NULL_ERROR);
        //用户数据获取
        UserInfo user = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getUserType, vo.getUserType())
                .eq(UserInfo::getMobile, vo.getPhoneNumber()));
        Assert.notNull(user, ResponseEnum.LOGIN_MOBILE_ERROR);
        //密码校验
        Assert.equals(SecureUtil.md5(password), user.getPassword(), ResponseEnum.LOGIN_PASSWORD_ERROR);
        //是否被锁定
        Assert.equals(user.getStatus(), UserInfo.STATUS_NORMAL, ResponseEnum.LOGIN_LOKED_ERROR);

        //2.数据填充
        //生成token
        String token = JwtUtils.createToken(user.getId(), user.getName());
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(user, userInfoVo);
        userInfoVo.setToken(token);

        //将数据存入登录记录
        UserLoginRecord userLoginRecord = new UserLoginRecord();
        userLoginRecord.setUserId(user.getId());
        userLoginRecord.setIp(ip);
        userLoginRecordMapper.insert(userLoginRecord);

        return userInfoVo;
    }

    @Override
    public Page<UserInfo> searchPage(Integer pageNum, Integer pageSize, SearchVo vo) {
        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
        if(vo != null) {
            wrapper.eq(StrUtil.isNotBlank(vo.getPhoneNumber()), UserInfo::getMobile, vo.getPhoneNumber())
                    .eq(vo.getStatus() != null, UserInfo::getStatus, vo.getStatus())
                    .eq(vo.getUserType() != null, UserInfo::getUserType, vo.getUserType());
        }

        Page<UserInfo> pageModel = this.page(new Page<>(pageNum, pageSize), wrapper);
        return pageModel;
    }

    @Override
    public void lock(Long id, Integer status) {
        UserInfo info = new UserInfo();
        info.setId(id);
        info.setStatus(status);
        this.updateById(info);
    }

    @Override
    public boolean checkPhone(String phoneNumber) {
        UserInfo one = this.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getMobile, phoneNumber));

        return one != null;
    }

    @Override
    public UserIndexVO getUserIndexById(Long userId) {
        //用户信息
        UserInfo userInfo = this.getById(userId);

        //用户账户信息
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, userId));

        //登录日志
        UserLoginRecord userLoginRecord = userLoginRecordMapper.selectOne(new LambdaQueryWrapper<UserLoginRecord>()
                .eq(UserLoginRecord::getUserId, userId)
                .orderByDesc(UserLoginRecord::getCreateTime)
                .last("limit 1"));

        UserIndexVO userIndexVO = new UserIndexVO();
        userIndexVO.setUserId(userId);
        userIndexVO.setName(userInfo.getName());
        userIndexVO.setNickName(userInfo.getNickName());
        userIndexVO.setUserType(userInfo.getUserType());
        userIndexVO.setHeadImg(userInfo.getHeadImg());
        userIndexVO.setBindStatus(userInfo.getBindStatus());
        userIndexVO.setAmount(userAccount.getAmount());
        userIndexVO.setFreezeAmount(userAccount.getFreezeAmount());
        userIndexVO.setLastLoginTime(userLoginRecord.getCreateTime());

        return userIndexVO;
    }
}
